﻿using Csla;
using Csla.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Csla.Security;
using Csla.Serialization;
using BizControl.DalLinq;
using BizControl.Library.BusinessObjects;
using BizControl.Library.BusinessObjects.People;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace BizControl.Library.Security
{
  [Serializable()]
  public class BizControlIdentity : CslaIdentity
  {
    public PersonBO Person { get; private set; }

    #region  Factory Methods

    internal static BizControlIdentity GetIdentity(string username, string password)
    {
      return DataPortal.Fetch<BizControlIdentity>(new UsernameCriteria(username, password));
    }

    internal static BizControlIdentity GetIdentity(string username)
    {
      return DataPortal.Fetch<BizControlIdentity>(new LoadOnlyCriteria(username));
    }

    private BizControlIdentity()
    { /* require use of factory methods */ }

    #endregion

    #region  Data Access

    [Serializable()]
    private class LoadOnlyCriteria
    {

      private string mUsername;

      public string Username
      {
        get
        {
          return mUsername;
        }
      }

      public LoadOnlyCriteria(string username)
      {
        mUsername = username;
      }
    }

    private void DataPortal_Fetch(UsernameCriteria criteria)
    {
      using (var ctx = ContextManager<BusinessControl2DataContext>.GetManager(Database.BizControlDB))
      {
        CryptographyManager defaultCrypto = EnterpriseLibraryContainer.Current.GetInstance<CryptographyManager>();

        var data = from u in ctx.DataContext.People
                   where u.Login == criteria.Username && !u.IsDeleted
                   select u;
        if (data.Count() > 0)
        {
          foreach (var person in data)
          {
            if (defaultCrypto.CompareHash(BizControl.Library.Constants.ConfiguraionNames.CryptoProvider512, criteria.Password, person.PasswordHash))
            {
              Fetch(person);
              return;
            }
          }
        }
        Fetch(null);
      }
    }

      private void DataPortal_Fetch(LoadOnlyCriteria criteria)
      {
        using (var ctx = ContextManager<BusinessControl2DataContext>.GetManager(Database.BizControlDB))
        {
          var data = from u in ctx.DataContext.People
                     where u.Login == criteria.Username && !u.IsDeleted
                     select u;
          if (data.Count() > 0)
            Fetch(data.Single());
          else
            Fetch(null);
        }
      }

      private void Fetch(Person user)
      {
        if (user != null)
        {
          Name = user.Login;
          IsAuthenticated = true;
          var roleList = new Csla.Core.MobileList<string>();
          var roles = from pr in user.PersonSecurityRoles 
                      select pr.SecurityRoleRef;
          foreach (var role in roles)
            roleList.Add(role.Name);
          Person = PersonBO.GetPerson(user.PersonId, true);
          roleList.Add(Person.ToString());
          Roles = roleList;
        }
        else
        {
          Name = "";
          IsAuthenticated = false;
          Roles = new Csla.Core.MobileList<string>();
          Person = null;
        }
      }

      #endregion
  }
}
